//The MIT License (MIT)
//
//Copyright (c) 2018 dote
//
//Permission is hereby granted, free of charge, to any person obtaining a copy of
//this software and associated documentation files (the "Software"), to deal in
//the Software without restriction, including without limitation the rights to
//use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
//the Software, and to permit persons to whom the Software is furnished to do so,
//subject to the following conditions:
//
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
//
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
//FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
//COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
//IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
//CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

package com.github.dote.mio.processor;


import com.github.dote.mio.ack.AckReceiveTask;
import com.github.dote.mio.ack.AckSendTask;
import com.github.dote.mio.client.UdpClient;
import com.github.dote.mio.client.IOClient;
import com.github.dote.mio.client.WebSocketClient;
import com.github.dote.mio.event.EventManager;
import com.github.dote.mio.protocal.Packet;
import com.github.dote.mio.protocal.PacketFactory;
import com.github.dote.mio.protocal.PacketType;
import com.github.dote.mio.session.SessionManager;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class EventMessageProcessor {

    private SessionManager sessionManager;
    private EventManager eventManager;
    private AckReceiveTask ackReceiveTask;

    public EventMessageProcessor(SessionManager sessionManager, EventManager eventManager,AckReceiveTask ackReceiveTask) {
        this.sessionManager = sessionManager;
        this.eventManager = eventManager;
        this.ackReceiveTask = ackReceiveTask;
    }

    /**
     * 分发
     *
     * @param client
     * @param packet
     */
    public void processEventMessage(IOClient client, Packet packet) {

        if (packet.getSessionId() == null || "".equals(packet.getSessionId()) || "0".equals(packet.getSessionId())) {
            processC2SEventMessage(client, packet);
        } else {
            processC2CEventMessage(client, packet);
        }
    }

    /**
     * Client-Server
     *
     * @param client
     * @param packet
     */
    public void processC2SEventMessage(IOClient client, Packet packet) {
        checkAndSendAckPakcet(client, packet);
        if ((client instanceof UdpClient)) {
            if(!ackReceiveTask.hasRecieved(packet.getAckId())){
                ackReceiveTask.put(packet.getAckId());
                eventManager.onEvent(client, packet.getSubType(), packet.getDataContent());
            }
        }else if(client instanceof WebSocketClient){
            eventManager.onEvent(client, packet.getSubType(), packet.getDataContent());
        }
    }

    /**
     * Client-Client
     *
     * @param client
     * @param packet
     */
    public void processC2CEventMessage(IOClient client, Packet packet) {
        //tranport
        String targetSessionId = packet.getSessionId();

        IOClient targetClient = sessionManager.getClient(targetSessionId);
        if (targetClient == null) {
            checkAndSendAckPakcet(client, packet);
            if (eventManager.onOfflinePacket(client, packet)) {
                //TODO
            }
        } else {
            if(targetClient instanceof  WebSocketClient){
                checkAndSendAckPakcet(client, packet);
            }
            String toSessionId = packet.getSessionId();
            packet.setSessionId(client.getSessionId());
            targetClient.transfer(packet, toSessionId);

        }
    }

    /**
     * 回确认包
     * @param client
     * @param packet
     */
    private void checkAndSendAckPakcet(IOClient client, Packet packet) {
        if ((client instanceof UdpClient)) {
            if (packet.isAck() && packet.getAckId() != null && !"".equals(packet.getAckId())) {
                client.send(PacketFactory.createAckPacket(packet));
            }
        }
    }


}
